package com.sse.sensor;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import com.sse.sensor.event.SensorEvent;
import com.sse.sensor.event.SensorEventListener;
import com.sse.util.TramaUtil;

/**
 * Clase Abstracta que define el funcionamiento basico de un sensor.
 * 
 * @author Jean Paul Manjarres Correal.
 * 
 */
public abstract class Sensor extends TimerTask implements ISensor {

	/** Identificador del sensor. */
	protected long id;
	
	/** Identificador de la casa. */
	protected int casaId;
	
	/** Constante que indica que el sensor no ha encontrado nada. */
	public static final long SIN_EVENTO = 0;
	
	/** Periodo de envio de senales del sensor*/
	protected int period = 1000;
	
	/** Lista de objetos que escuchan los mensajes */
	protected List<SensorEventListener> eventListenerList = new ArrayList<SensorEventListener>();
	
	/** Formato de fecha con hora.*/
	protected SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

	/** Identifica el tipo de sensor. */
	protected long tipoSensor;
	
	/** Posicion del sensor en eje x */
	protected int x;
	
	/** Posicion del sensor en eje y */
	protected int y;
	
	/**
	 * Agrega un nuevo listener para los eventos lanzados por este sensor.
	 */
	public void addSensorEventListener(SensorEventListener sensorEventListener) {
		eventListenerList.add(sensorEventListener);
	}

	/**
	 * Elimina un listener de la lista.
	 */
	public void removeSensorEventListener(
			SensorEventListener sensorEventListener) {
		eventListenerList.remove(sensorEventListener);
	}
	
	@Override
	public void removeAllSensorEventListener() {
		eventListenerList.clear();		
	}

	/**
	 * Dispara un evento nuevo.
	 * @param sensorEvent
	 */
	public void fireSensorEvent(SensorEvent sensorEvent) {
		for (SensorEventListener evl : eventListenerList) {
			evl.onEvent(sensorEvent);
		}
	}

	/**
	 * Inicia el funcionamiento de este sensor.
	 */
	public void iniciar() {
		Timer t = new Timer();
		t.scheduleAtFixedRate(this, 0, period);		
	}
	
	
	@Override
	public void run() {
		long evento = this.calcularEvento();	
		
		if(evento != SIN_EVENTO){			
			fireSensorEvent(new SensorEvent(TramaUtil.convertirValoresATrama(this.casaId, this.id, evento, this.tipoSensor, 0L)));
		}		
	}
	

	public void lanzarEventoManual(long evento){
		fireSensorEvent(new SensorEvent(TramaUtil.convertirValoresATrama(this.casaId, this.id, evento, this.tipoSensor, 0L)));
	}
	
	
	/**
	 * Metodo que calcula un evento a retornar.
	 * 
	 * @return
	 */
	public abstract long calcularEvento();


	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public int getPeriod() {
		return period;
	}

	public void setPeriod(int period) {
		this.period = period;
	}

	public long getTipoSensor() {
		return tipoSensor;
	}

	public void setTipoSensor(long tipoSensor) {
		this.tipoSensor = tipoSensor;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getCasaId() {
		return casaId;
	}

	public void setCasaId(int casaId) {
		this.casaId = casaId;
	}
}
